home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / warnings / warnings.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  14.0 KB  |  629 lines

  1. /* warnings.c: send warning messages back to originator */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/warnings/RCS/warnings.c,v 6.0 1991/12/18 20:13:32 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/warnings/RCS/warnings.c,v 6.0 1991/12/18 20:13:32 jpo Rel $
  9.  *
  10.  * $Log: warnings.c,v $
  11.  * Revision 6.0  1991/12/18  20:13:32  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16. #include "util.h"
  17. #include "retcode.h"
  18. #include "expand.h"
  19. #include "qmgr.h"
  20. #include "q.h"
  21. #include "prm.h"
  22. #include <sys/stat.h>
  23.  
  24. static int initialise();
  25. static struct type_Qmgr_DeliveryStatus *process(), *submit_warning();
  26. static int endfunc();
  27. static void dirinit();
  28. static ADDR *getnthrecip();
  29.  
  30. extern char *quedfldir, *loc_dom_site, *loc_dom_mta,
  31.     *getpostmaster(), *hdr_822_bp, *ia5_bp;
  32.  
  33. int     start_submit;
  34. CHAN    *mychan;
  35. #ifdef COPYTO_ADDRESS
  36. char    *copyAddr = NULLCP;
  37. #endif
  38.  
  39. /*   */
  40. /* main routine */
  41.  
  42. main (argc, argv)
  43. int     argc;
  44. char    **argv;
  45. {
  46.     sys_init(argv[0]);
  47.     dirinit ();
  48. #ifdef PP_DEBUG
  49.     if (argc>1 && strcmp(argv[1], "debug") == 0)
  50.         debug_channel_control(argc,argv,initialise,process,endfunc);
  51.     else
  52. #endif
  53.         channel_control(argc,argv,initialise,process,endfunc);
  54. }
  55.  
  56. /*   */
  57. /* move to correct place in file system */
  58.  
  59. static void dirinit()
  60. {
  61.     if (chdir (quedfldir) < 0)
  62.         err_abrt (RP_LIO,
  63.               "Unable to change directory to '%s'",
  64.               quedfldir);
  65. }
  66.  
  67. /*   */
  68. /* initialise */
  69.  
  70. static void decode_ch_info (info)
  71. char    *info;
  72. {
  73.     char    *info_copy;
  74.     int    margc, i;
  75.     char    *margv[100];
  76.     
  77. #ifdef COPYTO_ADDRESS
  78.     copyAddr = NULLCP;
  79. #endif
  80.     info_copy = strdup(info);
  81.     margc = sstr2arg(info_copy, 100, margv, ",=");
  82.     
  83.     for (i = 0; i < margc; i++) {
  84.         if (!isstr(margv[i]))
  85.             continue;
  86. #ifdef COPYTO_ADDRESS
  87.         if (lexequ(margv[i], "copy-to") == 0) {
  88.             i++;
  89.             if (i >= margc)
  90.                 copyAddr = getpostmaster(mychan->ch_out_ad_type);
  91.             else
  92.                 copyAddr = strdup(margv[i]);
  93.         } else
  94. #endif
  95.             PP_LOG (LLOG_EXCEPTIONS,
  96.                 ("Unrecognised ch_out_info element '%s'",
  97.                  margv[i]));
  98.     }
  99. }
  100.  
  101. static int initialise (arg)
  102. struct type_Qmgr_Channel *arg;
  103. {
  104.     char    *name = qb2str(arg);
  105.     
  106.     if ((mychan = ch_nm2struct(name)) == NULLCHAN) {
  107.         PP_OPER(NULLCP,
  108.             ("warnings: Channel '%s' not knpown",
  109.              name));
  110.         if (name) free(name);
  111.         return NOTOK;
  112.     }
  113.     
  114.     /* check is a warning channel */
  115.     if (mychan->ch_chan_type != CH_WARNING) {
  116.         PP_OPER(NULLCP,
  117.             ("warnings: Channel '%s' is not specified as type warning",
  118.              name));
  119.         if (name) free(name);
  120.     }
  121.     if (name) free(name);
  122.  
  123.     if (mychan->ch_out_info)
  124.         decode_ch_info(mychan->ch_out_info);
  125.  
  126.     start_submit = TRUE;
  127.  
  128.     return OK;
  129. }
  130.  
  131. /*   */
  132.  
  133. static void stop_io()
  134. {
  135.     if (start_submit == FALSE)
  136.         io_end(OK);
  137.     start_submit = TRUE;
  138. }
  139.  
  140. /* ARGSUSED */
  141. static int endfunc(arg)
  142. struct type_Qmgr_Channel    *arg;
  143. {
  144.     stop_io();
  145. }
  146.  
  147. /*   */
  148. /* routine to check if allowed to filter this message through this channel */
  149. static int security_check (msg)
  150. struct type_Qmgr_ProcMsg *msg;
  151. {
  152.      char         *msg_file = NULL, *msg_chan = NULL;
  153.     int        result;
  154.  
  155.     result = TRUE;
  156.     msg_file = qb2str (msg->qid);    
  157.     msg_chan = qb2str (msg->channel);
  158.  
  159.     if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) != 0)) {
  160.         PP_LOG(LLOG_EXCEPTIONS,
  161.                ("Chans/fcontrol channel err: '%s'",msg_chan));
  162.         result = FALSE;
  163.     }
  164.  
  165.     /* free all storage used */
  166.     if (msg_file != NULL) free(msg_file);
  167.     if (msg_chan != NULL) free(msg_chan);
  168.     return result;
  169. }
  170.  
  171. /*   */
  172. /* routine called to send warning */
  173.  
  174. static struct type_Qmgr_DeliveryStatus *process(arg)
  175. struct type_Qmgr_ProcMsg    *arg;
  176. {
  177.     struct prm_vars    prm;
  178.     Q_struct    que;
  179.     ADDR        *sender = NULLADDR;
  180.     ADDR        *recips = NULLADDR;
  181.     char        *this_msg;
  182.     int        rcounts;
  183.     struct type_Qmgr_DeliveryStatus    *retval;
  184.  
  185.  
  186.     prm_init (&prm);
  187.     q_init(&que);
  188.  
  189.     sender = recips = NULLADDR;
  190.  
  191.     delivery_init (arg->users);
  192.     delivery_setall (int_Qmgr_status_success); /* always lie! */
  193.  
  194.     if (security_check(arg) != TRUE)
  195.         return deliverystate;
  196.     
  197.     /* ok - send a warning */
  198.     this_msg = qb2str (arg->qid);
  199.     
  200.     
  201.     if (rp_isbad(rd_msg(this_msg, &prm, &que, 
  202.                 &sender, &recips, &rcounts))) {
  203.         PP_LOG(LLOG_EXCEPTIONS,
  204.                ("warnings: rd_msg error '%s'", this_msg));
  205.         rd_end();
  206.         if (this_msg) free(this_msg);
  207.         q_free(&que);
  208.         
  209.         return deliverystate;
  210.     }
  211.     
  212.     if (que.nwarns == NOTOK) /* old message */
  213.         return delivery_setall(int_Qmgr_status_success); /* lie */
  214.     fillin_expansions(&que, arg->users, this_msg);
  215.     
  216.     PP_NOTICE(("sending warning for msg %s", this_msg));
  217.     if ((retval = submit_warning(&que)) != 
  218.         (struct type_Qmgr_DeliveryStatus *) OK) {
  219.         rd_end();
  220.         return retval;
  221.     }
  222.  
  223.     inc_warnings(&que);
  224.     
  225.     rd_end();
  226.  
  227.     if (this_msg) free(this_msg);
  228.     q_free(&que);
  229.     prm_free(&prm);
  230.     
  231.     return delivery_setall (int_Qmgr_status_success);
  232. }
  233.  
  234. /*   */
  235.  
  236. inc_warnings(q)
  237. Q_struct    *q;
  238. {
  239.     q->nwarns++;
  240.     wr_q_nwarns(q);
  241. }
  242.  
  243. /*   */
  244. /* fillin the various things that can be expanded in the warning message */
  245.  
  246. Expand expand_macros[] = {
  247.     "sender",    NULLCP,    /* 0 */
  248.     "822sender",    NULLCP,    /* 1 */
  249.     "400sender",    NULLCP,    /* 2 */
  250.     "qid",        NULLCP,    /* 3 */
  251.     "ua-id",    NULLCP,    /* 4 */
  252.     "p1-id",    NULLCP,    /* 5 */
  253.     "recips",    NULLCP,    /* 6 */
  254.     "822recips",    NULLCP,    /* 7 */
  255.     "400recips",    NULLCP,    /* 8 */
  256.     "locmta",    NULLCP,    /* 9 */
  257.     "locsite",    NULLCP, /* 10 */
  258.     "hours-left",    NULLCP,    /* 11 */
  259.     NULLCP, NULLCP};
  260.  
  261. static char    *add_string(porig, add)
  262. char    **porig;
  263. char    *add;
  264. {
  265.     char    *new;
  266.  
  267.     if (*porig == NULLCP) 
  268.         new = strdup(add);
  269.     else {
  270.         new = malloc (strlen (*porig)
  271.                   + strlen ("\n")
  272.                   + strlen (add)
  273.                   + 1);
  274.         (void) sprintf(new, "%s\n%s",
  275.                    *porig,
  276.                    add);
  277.         free(*porig);
  278.     }
  279.     return new;
  280. }
  281.  
  282. fillin_expansions(q, users, this_msg)
  283. Q_struct    *q;
  284. struct type_Qmgr_UserList    *users;
  285. char        *this_msg;
  286. {
  287.     struct type_Qmgr_UserList    *ix;
  288.     ADDR    *adr;
  289.     char    *recips, *recips822, *recips400;
  290.     char    hbuf[64];
  291.     time_t now;
  292.  
  293.     recips = recips822 = recips400 = NULLCP;
  294.  
  295.     expand_macros[0].expansion = q->Oaddress->ad_value;
  296.     expand_macros[1].expansion = q->Oaddress->ad_r822adr;
  297.     expand_macros[2].expansion = q->Oaddress->ad_r400adr;
  298.     expand_macros[3].expansion = this_msg;
  299.     expand_macros[4].expansion = q->ua_id;
  300.     expand_macros[5].expansion = q->msgid.mpduid_string;
  301.     
  302.     for (adr = q -> Raddress; adr; adr = adr -> ad_next) {
  303.         if (adr -> ad_status == AD_STAT_PEND) {
  304.             recips = add_string(&recips, adr->ad_value);
  305.             recips822 = add_string(&recips822, adr->ad_r822adr);
  306.             recips400 = add_string(&recips400, adr->ad_r400adr);
  307.         }
  308.     }
  309.     if (expand_macros[6].expansion)
  310.         free(expand_macros[6].expansion);
  311.     expand_macros[6].expansion = recips;
  312.  
  313.     if (expand_macros[7].expansion)
  314.         free(expand_macros[7].expansion);
  315.     expand_macros[7].expansion = recips822;
  316.  
  317.     if (expand_macros[8].expansion)
  318.         free(expand_macros[8].expansion);
  319.     expand_macros[8].expansion = recips400;
  320.     expand_macros[9].expansion = loc_dom_mta;
  321.     expand_macros[10].expansion = loc_dom_site;
  322.     (void) time (&now);
  323.     (void) sprintf (hbuf, "%d", 
  324.             q -> retinterval - 
  325.                 ((now - utc2time_t(q -> queuetime)) / 3600));
  326.     expand_macros[11].expansion = strdup(hbuf);
  327. }
  328.  
  329. /*   */
  330. /* submit warning message */
  331.  
  332. static char    *expand_line(line)
  333. char    *line;
  334. {
  335.     char    *margv[100], *ret, *cp;
  336.     int    margc, len, i;
  337.     
  338.     cp = strdup(line);
  339.     compress(cp, cp);
  340.     if (*cp == '\0') {
  341.         free(cp);
  342.         return strdup(line);
  343.     }
  344.     if (index (line, '$')) 
  345.         ret = expand_dyn (line, expand_macros);
  346.     else 
  347.         ret = strdup (line);
  348.     return ret;
  349. }
  350.  
  351. /* for now */
  352. extern char    *wrndfldir, *wrnfile;
  353.  
  354. static char    *q2warnfile(q)
  355. Q_struct    *q;
  356. {
  357.     static char    filename[MAXPATHLENGTH];
  358.     struct stat statbuf;
  359.     
  360.     (void) sprintf(filename,
  361.                "%s/%s.%d",
  362.                wrndfldir,
  363.                wrnfile,
  364.                q->nwarns + 1);
  365.  
  366.     if (stat(filename, &statbuf) == OK)
  367.         return filename;
  368.  
  369.     /* try for default warning */
  370.     (void) sprintf(filename,
  371.                "%s/%s",
  372.                wrndfldir,
  373.                wrnfile);
  374.     if (stat(filename, &statbuf) == OK)
  375.         return filename;
  376.     return NULLCP;
  377. }
  378.  
  379. static void submit_error(proc, rp)
  380. char    *proc;
  381. RP_Buf    *rp;
  382. {
  383.     PP_LOG(LLOG_EXCEPTIONS,
  384.            ("Chans/warnings %s failure [%s]",
  385.         proc, rp->rp_line));
  386.     start_submit = TRUE;
  387.     io_end(NOTOK);
  388. }
  389.  
  390. #define fold_and_submit_line submit_line
  391.  
  392. static struct type_Qmgr_DeliveryStatus *submit_line(line, rp)
  393. char    *line;
  394. RP_Buf    *rp;
  395. {
  396.     if (rp_isbad(io_tdata (line, strlen(line)))) {
  397.         submit_error ("io_tdata", rp);
  398.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  399.                          "io_tdata failed");
  400.     }
  401.     return (struct type_Qmgr_DeliveryStatus *) OK;
  402. }
  403.  
  404. static struct type_Qmgr_DeliveryStatus *submit_warning(q)
  405. Q_struct    *q;
  406. {
  407.     struct prm_vars    prm;
  408.     Q_struct    qs;
  409.     char        *warningfile;
  410.     RP_Buf        reply;
  411.     char        buffer[BUFSIZ], timestr[BUFSIZ], *expanded;
  412.     struct type_Qmgr_DeliveryStatus *retval;
  413.     FILE        *fp;
  414.     UTC    now, start_time, utclocalise ();
  415.  
  416.  
  417.     now = utcnow ();
  418.     start_time = utclocalise (now);
  419.     free ((char *)now);
  420.  
  421.     prm_init(&prm);
  422.     q_init(&qs);
  423.     
  424.     qs.inbound = list_rchan_new (loc_dom_site, 
  425.                      mychan->ch_name);
  426.     qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp);
  427.     list_bpt_add(&qs.encodedinfo.eit_types,
  428.              list_bpt_new (ia5_bp));
  429.     qs.Oaddress = adr_new (getpostmaster(AD_822_TYPE), AD_822_TYPE, 0);
  430.     qs.Raddress = adr_new (q->Oaddress->ad_r822adr, AD_822_TYPE, 1);
  431. #ifdef COPYTO_ADDRESS
  432.     if (copyAddr != NULLCP)
  433.         qs.Raddress->ad_next = adr_new(copyAddr, 
  434.                            mychan->ch_out_ad_type, 1);
  435. #endif
  436.     
  437.     /* select which template warning message to use */
  438.     if ((warningfile = q2warnfile(q)) == NULLCP) {
  439.         PP_LOG(LLOG_EXCEPTIONS,
  440.                ("unable to find warnings template warning"));
  441.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  442.                          "unable to find warnings template file");
  443.     }
  444.  
  445.     /* check submission started */
  446.     if (start_submit == TRUE
  447.         && rp_isbad (io_init (&reply))) {
  448.         submit_error ("io_init", &reply);
  449.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  450.                          "unable to start submit");
  451.     }
  452.  
  453.     if (rp_isbad (io_wprm(&prm, &reply))) {
  454.         submit_error ("io_wprm", &reply);
  455.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  456.                          "io_wprm failed");
  457.     }
  458.  
  459.     if (rp_isbad (io_wrq(&qs, &reply))) {
  460.         submit_error ("io_wrq", &reply);
  461.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  462.                          "io_wrq failed");
  463.     }
  464.  
  465.     /* from postmaster@loc_dom_site */
  466.     if (rp_isbad(io_wadr (qs.Oaddress, AD_ORIGINATOR, &reply))) {
  467.         submit_error ("io_wadr(postmaster)", &reply);
  468.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  469.                          "io_wadr(postamster) failed");
  470.     }
  471.     
  472.     /* to originator of message */
  473.  
  474.     if (rp_isbad(io_wadr (qs.Raddress, AD_RECIPIENT, &reply))) {
  475.         submit_error ("io_wadr(recipient)", &reply);
  476.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  477.                          "io_wadr(recipient) failed");
  478.     }
  479.  
  480. #ifdef COPYTO_ADDRESS
  481.     if (copyAddr != NULLCP &&
  482.         qs.Raddress->ad_next != NULLADDR) {
  483.         if (rp_isbad(io_wadr (qs.Raddress->ad_next, AD_RECIPIENT, &reply))) {
  484.             submit_error ("io_wadr(recipient)", &reply);
  485.             return delivery_setallstate (int_Qmgr_status_messageFailure,
  486.                              "io_wadr(recipient) failed");
  487.         }
  488.     }
  489. #endif
  490.  
  491.     if (rp_isbad (io_adend (&reply))) {
  492.         submit_error ("io_adend", &reply);
  493.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  494.                          "io_adend failed");
  495.     }
  496.  
  497.     if (rp_isbad (io_tinit(&reply))) {
  498.         submit_error ("io_tinit", &reply);
  499.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  500.                          "io_tinit failed");
  501.     }
  502.  
  503.     /* submit header */
  504.     
  505.     if (rp_isbad (io_tpart (hdr_822_bp, FALSE, &reply))) {
  506.         submit_error ("io_tpart", &reply);
  507.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  508.                          "io_tpart failed");
  509.     }
  510.  
  511.     (void) sprintf(buffer, "From: %s\n", qs.Oaddress->ad_value);
  512.     
  513.     if ((retval = submit_line(buffer, &reply)) != 
  514.         (struct type_Qmgr_DeliveryStatus *) OK) {
  515.         return retval;
  516.     }
  517.  
  518.     (void) sprintf(buffer, "To: %s\n", qs.Raddress->ad_value);
  519.     
  520.     if ((retval = submit_line(buffer, &reply)) != 
  521.         (struct type_Qmgr_DeliveryStatus *) OK) {
  522.         return retval;
  523.     }
  524.  
  525. #ifdef COPYTO_ADDRESS
  526.     if (copyAddr != NULLCP) {
  527.         (void) sprintf(buffer, "Cc: %s\n", 
  528.                    copyAddr);
  529.         if ((retval = submit_line(buffer, &reply)) != 
  530.             (struct type_Qmgr_DeliveryStatus *) OK) {
  531.             return retval;
  532.         }
  533.     }
  534. #endif
  535.     (void) UTC2rfc (start_time, timestr);
  536.     free ((char *)start_time);
  537.     start_time = NULLUTC;
  538.     
  539.     (void) sprintf(buffer,
  540.                "Date: %s\n",
  541.                timestr);
  542.  
  543.     if ((retval = submit_line(buffer, &reply)) != 
  544.         (struct type_Qmgr_DeliveryStatus *) OK) {
  545.         return retval;
  546.     }
  547.  
  548.  
  549.     (void) sprintf(buffer, 
  550.                "Subject: WARNING: message delayed at \"%s\"\n",
  551.                loc_dom_site);
  552.  
  553.     if ((retval = submit_line(buffer, &reply)) != 
  554.         (struct type_Qmgr_DeliveryStatus *) OK) {
  555.         return retval;
  556.     }
  557.     
  558.     if (rp_isbad(io_tdend (&reply))) {
  559.         submit_error("io_tdend", &reply);
  560.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  561.                          "io_tdend failed");
  562.     }
  563.  
  564.     (void) sprintf(buffer, "1.%s", ia5_bp);
  565.     if (rp_isbad(io_tpart(buffer, FALSE, &reply))) {
  566.         submit_error ("io_tpart", &reply);
  567.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  568.                          "io_tpart failed");
  569.     }
  570.  
  571.     /* submit text of message */
  572.  
  573.     if ((fp = fopen (warningfile, "r")) == NULL) {
  574.         PP_SLOG (LLOG_EXCEPTIONS,
  575.              warningfile,
  576.              ("Can't open file"));
  577.         stop_io();
  578.         return delivery_setallstate(int_Qmgr_status_messageFailure,
  579.                         "failed to open warnings file");
  580.     }
  581.  
  582.     while (fgets (buffer, sizeof buffer, fp) != NULL) {
  583.         /* expand macros in that line */
  584.  
  585.         if ((expanded = expand_line(buffer)) == NULLCP) {
  586.             PP_LOG(LLOG_EXCEPTIONS,
  587.                    ("Unable to expand line in warning file '%s'",
  588.                    warningfile));
  589.             fclose(fp);
  590.             stop_io();
  591.             return delivery_setallstate 
  592.                 (int_Qmgr_status_messageFailure,
  593.                  "expansion of line failed");
  594.         }
  595.        
  596.         if ((retval = fold_and_submit_line(expanded, &reply)) != 
  597.             (struct type_Qmgr_DeliveryStatus *) OK) {
  598.             fclose (fp);
  599.             return retval;
  600.         }
  601.     
  602.         free(expanded);
  603.  
  604.     }    
  605.  
  606.     fclose(fp);
  607.     if (rp_isbad(io_tdend (&reply))
  608.         || rp_isbad(io_tend (&reply))) {
  609.         submit_error("io_tend failed", &reply);
  610.         return delivery_setallstate(int_Qmgr_status_messageFailure,
  611.                         "io_tend failed");
  612.     }
  613.     
  614.     return (struct type_Qmgr_DeliveryStatus *) OK;
  615. }
  616.     
  617. static ADDR *getnthrecip(que, num)
  618. Q_struct    *que;
  619. int        num;
  620. {
  621.     ADDR *ix = que->Raddress;
  622.  
  623.     if (num == 0)
  624.         return que->Oaddress;
  625.     while ((ix != NULL) && (ix->ad_no != num))
  626.         ix = ix->ad_next;
  627.     return ix;
  628. }
  629.